using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
using Soopah.Xna.Input;
using XNADirectInput;

namespace XDIbuttonMapper
{
    /// <summary>
    /// The Game that runs in the Form
    /// </summary>
    public class XDIMapper : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        public DirectInputGamepad gp;
        Texture2D X, Y, A, B, Back, Start, RB, LB, RT, LT, RS, LS, DPad,DPU,DPD,DPL,DPR,LSL,LSR,LSU,LSD,RSR,RSL,RSD,RSU;
        SpriteFont Font;
        IntPtr DrawSurface;
        public bool ShowDiagnostic;
        public XDI xdi;

        bool bX, bY, bA, bB, bBack, bStart, bRB, bLB, bRT, bLT, bRS, bLS, bLSU,bLSD,bLSR,bLSL,bRSR,bRSL,bRSU,bRSD,bDU,bDD,bDR,bDL;

        public XDIMapper()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
            ButtonSettings bs = new ButtonSettings();
            DirectInputGamepadManager.ReloadGamepads();
            if (DirectInputGamepadManager.Gamepads[0] != null)
            {
                gp = DirectInputGamepadManager.Gamepads[0];
                gp.LoadSettings(StorageContainer.TitleLocation + @"\Devices\" + gp.PadName);
            }
        }

        public XDIMapper(IntPtr drawSurface)
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
            DrawSurface = drawSurface;
            graphics.PreparingDeviceSettings += new EventHandler<PreparingDeviceSettingsEventArgs>(graphics_PreparingDeviceSettings);
            System.Windows.Forms.Control.FromHandle(this.Window.Handle).VisibleChanged += new EventHandler(Game1_VisibleChanged);
            DirectInputGamepadManager.ReloadGamepads();
            if (DirectInputGamepadManager.Gamepads.Count >0)
            {
                gp = DirectInputGamepadManager.Gamepads[0];
                gp.LoadSettings(StorageContainer.TitleLocation + @"\Devices\" + gp.PadName);
            }
        }

        void graphics_PreparingDeviceSettings(object sender, PreparingDeviceSettingsEventArgs e)
        {
                e.GraphicsDeviceInformation.PresentationParameters.DeviceWindowHandle =
                DrawSurface;
        }
 
        /// <summary>
        /// Occurs when the original gamewindows' visibility changes and makes sure it stays invisible
        /// </summary>
        ///
        private void Game1_VisibleChanged(object sender, EventArgs e)
        {
                if (System.Windows.Forms.Control.FromHandle((this.Window.Handle)).Visible == true)
                    System.Windows.Forms.Control.FromHandle((this.Window.Handle)).Visible = false;
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // TODO: Add your initialization logic here

            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            xdi = new XDI(this);
            xdi.LoadFromContent("DeviceSettings");

            bX=false;
            bY=false;
            bA=false;
            bB=false;
            bBack=false;
            bStart=false;
            bRB=false;
            bLB=false;
            bRT=false;
            bLT=false;
            bRS=false;
            bLS = false;
            
            spriteBatch = new SpriteBatch(GraphicsDevice);
            X = Content.Load<Texture2D>(@"ButtonImages\xboxControllerButtonX");
            Y = Content.Load<Texture2D>(@"ButtonImages\xboxControllerButtonY");
            A = Content.Load<Texture2D>(@"ButtonImages\xboxControllerButtonA");
            B = Content.Load<Texture2D>(@"ButtonImages\xboxControllerButtonB");
            Back = Content.Load<Texture2D>(@"ButtonImages\xboxControllerBack");
            Start = Content.Load<Texture2D>(@"ButtonImages\xboxControllerStart");
            RB = Content.Load<Texture2D>(@"ButtonImages\xboxControllerRightShoulder");
            LB = Content.Load<Texture2D>(@"ButtonImages\xboxControllerLeftShoulder");
            RT = Content.Load<Texture2D>(@"ButtonImages\xboxControllerRightTrigger");
            LT = Content.Load<Texture2D>(@"ButtonImages\xboxControllerLeftTrigger");
            LS = Content.Load<Texture2D>(@"ButtonImages\xboxControllerLeftThumbstick");
            RS = Content.Load<Texture2D>(@"ButtonImages\xboxControllerRightThumbstick"); 
            DPad = Content.Load<Texture2D>(@"ButtonImages\xboxControllerDPad");

            DPD = Content.Load<Texture2D>(@"ButtonImages\DPDown");
            DPU = Content.Load<Texture2D>(@"ButtonImages\DPup");
            DPL = Content.Load<Texture2D>(@"ButtonImages\DPLeft");
            DPR = Content.Load<Texture2D>(@"ButtonImages\DPRight");

            RSU =Content.Load<Texture2D>(@"ButtonImages\RSUp");
            RSD = Content.Load<Texture2D>(@"ButtonImages\RSDown");
            RSL = Content.Load<Texture2D>(@"ButtonImages\RSLeft");
            RSR = Content.Load<Texture2D>(@"ButtonImages\RSRight");

            LSL = Content.Load<Texture2D>(@"ButtonImages\LSLeft");
            LSR = Content.Load<Texture2D>(@"ButtonImages\LSRight");
            LSD = Content.Load<Texture2D>(@"ButtonImages\LSDown");
            LSU = Content.Load<Texture2D>(@"ButtonImages\LSUp");


            
            Font = Content.Load<SpriteFont>("Font");
            if (ContentLoaded != null)
                ContentLoaded(this, new EventArgs());
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }


        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            if (gp != null)
            {
                #region Buttons
                if (gp.Buttons.A == ButtonState.Pressed)
                    bA = true;
                else bA = false;

                if (gp.Buttons.B == ButtonState.Pressed)
                    bB = true;
                else bB = false;

                if (gp.Buttons.X == ButtonState.Pressed)
                    bX = true;
                else bX = false;

                if (gp.Buttons.Y == ButtonState.Pressed)
                    bY = true;
                else bY = false;

                if (gp.Buttons.LeftShoulder == ButtonState.Pressed)
                    bLB = true;
                else bLB = false;

                if (gp.Buttons.RightShoulder == ButtonState.Pressed)
                    bRB = true;
                else bRB = false;

                if (gp.Buttons.Back == ButtonState.Pressed)
                    bBack = true;
                else bBack = false;

                if (gp.Buttons.Start == ButtonState.Pressed)
                    bStart = true;
                else bStart = false;

                if (gp.Buttons.LeftStick == ButtonState.Pressed)
                    bLS = true;
                else bLS = false;

                if (gp.Buttons.RightStick == ButtonState.Pressed)
                    bRS = true;
                else bRS = false;
                #endregion
                bool b = gp.Device.Caps.ForceFeedback;
                #region Shoulders
                if (gp.ThumbSticks.Third.Y > 0.05)
                    bLT = true;
                else bLT = false;

                if (gp.ThumbSticks.Third.Y < -0.05)
                    bRT = true;
                else bRT = false;

                #endregion

                #region LeftStick

                if (gp.ThumbSticks.Left.X < -.03)
                    bLSL = true;
                else
                    bLSL = false;

                if (gp.ThumbSticks.Left.X > .03)
                    bLSR = true;
                else
                    bLSR = false;

                if (gp.ThumbSticks.Left.Y > .03)
                    bLSU = true;
                else
                    bLSU = false;

                if (gp.ThumbSticks.Left.Y < -.03)
                    bLSD = true;
                else
                    bLSD = false;
                #endregion

                #region RightStick
                if (gp.ThumbSticks.Right.X < -.05)
                    bRSL = true;
                else
                    bRSL = false;

                if (gp.ThumbSticks.Right.X > .05)
                    bRSR = true;
                else
                    bRSR = false;

                if (gp.ThumbSticks.Right.Y > .05)
                    bRSU = true;
                else
                    bRSU = false;

                if (gp.ThumbSticks.Right.Y < -.05)
                    bRSD = true;
                else
                    bRSD = false;
                #endregion

                #region DPad
                if (gp.DPad.Down == ButtonState.Pressed)
                    bDD = true;
                else
                    bDD = false;

                if (gp.DPad.Up == ButtonState.Pressed)
                    bDU = true;
                else
                    bDU = false;

                if (gp.DPad.Left == ButtonState.Pressed)
                    bDL = true;
                else
                    bDL = false;

                if (gp.DPad.Right == ButtonState.Pressed)
                    bDR = true;
                else
                    bDR = false;
                #endregion
            }
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.Black);
            Vector2 Position = new Vector2(50,50);

            if (!ShowDiagnostic)
            {
                #region DrawControls
                spriteBatch.Begin();
                spriteBatch.Draw(LT, Position, bLT ? Color.DarkGray : Color.White);

                Position.X += 600;
                spriteBatch.Draw(RT, Position, bRT ? Color.DarkGray : Color.White);

                Position.X -= 500;
                spriteBatch.Draw(LB, Position, bLB ? Color.DarkGray : Color.White);

                Position.X += 250;
                spriteBatch.Draw(RB, Position, bRB ? Color.DarkGray : Color.White);

                Position.X -= 350;
                Position.Y += 180;

                #region LeftStick
                spriteBatch.Draw(LS, Position, bLS ? Color.Yellow : Color.White);

                spriteBatch.Draw(LSU, Position, bLSU ? Color.Yellow : Color.White);
                spriteBatch.Draw(LSD, Position, bLSD ? Color.Yellow : Color.White);
                spriteBatch.Draw(LSL, Position, bLSL ? Color.Yellow : Color.White);
                spriteBatch.Draw(LSR, Position, bLSR ? Color.Yellow : Color.White);
                #endregion

                Position.X += 500;
                Position.Y -= 50;
                spriteBatch.Draw(Y, Position, bY ? Color.DarkGray : Color.White);

                Position.X -= 300;
                Position.Y += 90;
                spriteBatch.Draw(Back, Position, bBack ? Color.DarkGray : Color.White);
                Position.X += 150;
                spriteBatch.Draw(Start, Position, bStart ? Color.DarkGray : Color.White);
                Position.X += 100;
                spriteBatch.Draw(X, Position, bX ? Color.DarkGray : Color.White);
                Position.X += 120;
                spriteBatch.Draw(B, Position, bB ? Color.DarkGray : Color.White);
                Position.X -= 60;
                Position.Y += 100;
                spriteBatch.Draw(A, Position, bA ? Color.DarkGray : Color.White);

                Position.X -= 450;
                Position.Y += 25;

                #region DPad
                spriteBatch.Draw(DPad, Position, Color.White);

                spriteBatch.Draw(DPU, Position, bDU ? Color.Yellow : Color.White);
                spriteBatch.Draw(DPD, Position, bDD ? Color.Yellow : Color.White);
                spriteBatch.Draw(DPL, Position, bDL ? Color.Yellow : Color.White);
                spriteBatch.Draw(DPR, Position, bDR ? Color.Yellow : Color.White);
                #endregion
                Position.X += 300;

                #region RightStick
                spriteBatch.Draw(RS, Position, bRS ? Color.Yellow : Color.White);
                spriteBatch.Draw(RSU, Position, bRSU ? Color.Yellow : Color.White);
                spriteBatch.Draw(RSD, Position, bRSD ? Color.Yellow : Color.White);
                spriteBatch.Draw(RSL, Position, bRSL ? Color.Yellow : Color.White);
                spriteBatch.Draw(RSR, Position, bRSR ? Color.Yellow : Color.White);
                #endregion

                spriteBatch.End();
                #endregion
            }
            else
            {
                if (gp != null)
                {
                    spriteBatch.Begin();
                    spriteBatch.DrawString(Font, gp.DiagnosticsRawGamepadData, Vector2.Zero, Color.White);
                    spriteBatch.DrawString(Font, gp.DiagnosticsButtons, new Vector2(0, Font.MeasureString(gp.DiagnosticsRawGamepadData).Y), Color.AliceBlue);
                    spriteBatch.End();
                }
            }
            base.Draw(gameTime);
        }

        public event EventHandler ContentLoaded;
    }
}
